﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.DirectX.DirectSound;
using System.IO;

namespace SpeechToText.STT
{
    public class WavHeader
    {
        /// <summary>
        /// Создает заголовок для wav файла.
        /// </summary>
        /// <param name="wavFormat"></param>
        /// <param name="DataLength"> количество записываемых байт </param>
        /// <returns></returns>
        public static byte[] MakeWavHeader(WaveFormat wavFormat, int DataLength)
        {
            byte[] header = new byte[44];
            MemoryStream ms = new MemoryStream(header, 0, 44, true);
            UTF8Encoding utf8 = new UTF8Encoding();

            ms.Write(utf8.GetBytes("RIFF"), 0, 4);
            ms.Write(BitConverter.GetBytes(DataLength + 36), 0, 4);
            ms.Write(utf8.GetBytes("WAVE"), 0, 4);
            ms.Write(utf8.GetBytes("fmt "), 0, 4);
            ms.Write(BitConverter.GetBytes(16), 0, 4);
            ms.Write(BitConverter.GetBytes((short)wavFormat.FormatTag), 0, 2);
            ms.Write(BitConverter.GetBytes(wavFormat.Channels), 0, 2);
            ms.Write(BitConverter.GetBytes(wavFormat.SamplesPerSecond), 0, 4);
            ms.Write(BitConverter.GetBytes(wavFormat.AverageBytesPerSecond), 0, 4);
            ms.Write(BitConverter.GetBytes(wavFormat.BlockAlign), 0, 2);
            ms.Write(BitConverter.GetBytes(wavFormat.BitsPerSample), 0, 2);
            ms.Write(utf8.GetBytes("data"), 0, 4);
            ms.Write(BitConverter.GetBytes(DataLength), 0, 4);

            ms.Close();

            return header;
        }
        
        /// <summary>
        /// Берет из массива первые 44 байта. и читает их них параметры wav записи.
        /// </summary>
        /// <param name="ByteArray"> wav файл или его заголовок в виде массива байт.</param>
        /// <returns></returns>
        public static WaveFormat GetWavFormat(byte[] ByteArray)
        {
            WaveFormat WF = new WaveFormat();

            WF.AverageBytesPerSecond = BitConverter.ToInt32(ByteArray, 28);
            WF.BitsPerSample = BitConverter.ToInt16(ByteArray, 34);
            WF.BlockAlign = BitConverter.ToInt16(ByteArray, 32);
            WF.Channels = BitConverter.ToInt16(ByteArray, 22);
            WF.FormatTag = (WaveFormatTag) BitConverter.ToInt16(ByteArray, 20);
            WF.SamplesPerSecond = BitConverter.ToInt32(ByteArray, 24);

            return WF;
        }

        /// <summary>
        /// Создает весь waveformat используя только 3 параметра
        /// </summary>
        /// <param name="samplingRate"></param>
        /// <param name="bitsPerSample"></param>
        /// <param name="channels"></param>
        /// <returns></returns>
        public static WaveFormat CreateWaveFormat(int samplingRate, short bitsPerSample, short channels)
        {
            WaveFormat waveFormat = new WaveFormat();

            waveFormat.SamplesPerSecond = samplingRate;
            waveFormat.BitsPerSample = bitsPerSample;
            waveFormat.Channels = channels;
            waveFormat.FormatTag = WaveFormatTag.Pcm;
            waveFormat.BlockAlign = (short)(waveFormat.Channels * (waveFormat.BitsPerSample / 8));
            waveFormat.AverageBytesPerSecond = waveFormat.SamplesPerSecond * waveFormat.BlockAlign;

            return waveFormat;
        }
        
        /// <summary>
        ///  На свое усмотрение составит wav формат ориентируясь на частоту записи
        /// </summary>
        /// <param name="samplingRate"></param>
        /// <returns></returns>
        public static WaveFormat CreateWaveFormat(int samplingRate)
        {
            if (samplingRate < 11025) samplingRate = 11025;
            else if (samplingRate > 11025 && samplingRate < 22050) samplingRate = 22050;
            else if (samplingRate > 22050 && samplingRate < 44100) samplingRate = 44100;
            else if (samplingRate > 44100 && samplingRate < 96000) samplingRate = 96000;
            else if (samplingRate > 96000) samplingRate = 96000;

            short bitsPerSample;
            short channels;

            if (samplingRate <= 22050) bitsPerSample = 8;
            else bitsPerSample = 16;

            if (samplingRate <= 22050) channels = 1;
            else channels = 2;

            return CreateWaveFormat(samplingRate, bitsPerSample, channels);
        }
    }
}
